package com.ehotting.mqbd.core.service.mq;

import com.alibaba.fastjson.JSON;
import com.ehotting.eaf.core.StringHelper;
import com.ehotting.eaf.core.utils.AssertUtils;
import com.ehotting.mqbd.api.MQDBConstants;
import com.ehotting.mqbd.api.MqDataStateConstants;
import com.ehotting.mqbd.api.TaskStateActionConstants;
import com.ehotting.mqbd.api.bean.*;
import com.ehotting.mqbd.api.bean.solver.ModuleInfoBean;
import com.ehotting.mqbd.api.enums.*;
import com.ehotting.mqbd.core.config.MqbdCorePropertyConfig;
import com.ehotting.mqbd.core.logger.LOGGER_KEY;
import com.ehotting.mqbd.core.manager.AgentLinkManager;
import com.ehotting.mqbd.core.manager.ModuleManager;
import com.ehotting.mqbd.core.manager.MsgStateManager;
import com.ehotting.mqbd.core.manager.SolverStateManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;


@Component
public class MQDataHelper {

    private static final Logger logger = LoggerFactory.getLogger(MQDataHelper.class);

    @Autowired
    private ModuleManager moduleManager;
    @Autowired
    private MsgStateManager msgStateManager;
    @Autowired
    private AgentLinkManager agentLinkManager;
    @Autowired
    private SolverStateManager solverStateManager;
    @Autowired
    private MqbdCorePropertyConfig mqbdCorePropertyConfig;

    public void setPreValue(MQDataAble data){
        data.loadClazz();
        handleRequestData(data);
        handleResponseData(data);
        MDC.put(LOGGER_KEY.MODULE,data.getModule());
        if(data.isLogRequest()){
            MDC.put(LOGGER_KEY.REQUEST, JSON.toJSONString(data));
        }
        MDC.put(LOGGER_KEY.START_TIME, String.valueOf(System.currentTimeMillis()));
    }

    private void setSolverIp(MQDataAble data, ModuleInfoBean sysModuleInfo){
        if(sysModuleInfo.getSolveStep() == SolveStepEnum.MULTI) {
            if (StringUtils.isEmpty(data.getSolverIp())) {
                data.setSolverIp(solverStateManager.getAndBinByModelAndAgentIdOrDefault(data.getAgentId()));
            }
        }
    }

    private void handleRequestData(MQDataAble data){
        if(DirectionEnum.REQUEST.getCode().equals(data.getDirection())){
            ModuleInfoBean sysModuleInfo = moduleManager.getByModule(data.getModule());
            AssertUtils.notNull(sysModuleInfo,"sysModuleInfo["+data.getModule()+"] is null");
            logger.info("sysModuleInfo:{}", JSON.toJSONString(sysModuleInfo));
            if(sysModuleInfo.getSolveStep() == SolveStepEnum.MULTI){
                data.setSolveStep(SolveStepEnum.MULTI);
            }
            setAutoTopic(data,sysModuleInfo);
            setSolverIp(data,sysModuleInfo);
            setConsumerIp(data,sysModuleInfo);
            setCancel(sysModuleInfo,data);
        }
    }

    private void handleResponseData(MQDataAble data){
        if(DirectionEnum.RESPONSE.getCode().equals(data.getDirection())){
            setResponseSolverIp(data);
        }
    }

    private void setResponseSolverIp(MQDataAble data){
        /**消息返回时，nodeId设置为空**/
        data.setSolverIp(null);
    }

    private void setConsumerIp(MQDataAble data, ModuleInfoBean sysModuleInfo){
        if(sysModuleInfo.getSolveStep() == SolveStepEnum.MULTI
                && MQDBConstants.DISPATCHER_HOST.equals(data.getConsumerHost()) ) {
            String consumerIp = agentLinkManager.getConsumerIpAndAgentId(data.getModule(),data.getAgentId());
            if(StringHelper.hasText(consumerIp)){
                data.setConsumerHost(consumerIp);
            }
        }
    }

    private void setAutoTopic(MQDataAble data, ModuleInfoBean sysModuleInfo){
        if( data.isAutoTopic() == true
                && data.getRequest() instanceof CommonRequest) {
            CommonRequest request = (CommonRequest)data.getRequest();
            TopicEnum topic = autoTopic(sysModuleInfo,request.getRequestUrl());
            if(TopicEnum.BLOCK == topic ){
                data.setSync(false);
                if(data.isAutoPush()){
                    data.setPushModel(MQDataPushModelEnum.WEBSOCKET_PUSH);
                }
            }
            data.setTopic(topic);
        }
    }

    private void setCancel(ModuleInfoBean sysModuleInfo, MQDataAble data){
        if( ProtocolTypeEnum.HTTP == data.getProtocolType() && data.getRequest() instanceof CommonRequest){
            CommonRequest request = (CommonRequest)data.getRequest();
            cancelForHttp(sysModuleInfo,data,request.getRequestUrl());
        }
        if(ProtocolTypeEnum.TCP == data.getProtocolType()){
            cancelForTcp(data);
        }
    }

    public TopicEnum autoTopic(ModuleInfoBean sysModuleInfo, String url){
        logger.info("sysModuleInfo:{}", JSON.toJSONString(sysModuleInfo));
        logger.info("url:{}", url);
        if(com.ehotting.eaf.core.utils.StringUtils.matches(url, sysModuleInfo.getBlockUrl())){
            return TopicEnum.BLOCK;
        }
        return TopicEnum.CONCURRENCY;
    }

    public void cancelForHttp(ModuleInfoBean sysModuleInfo, MQDataAble mqData, String url){
        if(com.ehotting.eaf.core.utils.StringUtils.matches(url, sysModuleInfo.getCancelUrl())){
//            MsgStateBean msgState = msgStateManager.isInQueue(mqData.getAgentId());
//            if(msgState!=null){
//                mqData.setState(MqDataStateConstants.TASK_CANCEL_IN_QUEUE);
//                mqData.setMsg(msgState.getSerial());
//            }
            msgStateManager.cancel(mqData.getAgentId());
        }
    }

    public void cancelForTcp(MQDataAble mqData){
        if(TaskStateActionConstants.TASK_CANCEL.equals(mqData.getAction())){
            msgStateManager.cancel(mqData.getAgentId());
        }
    }

    public boolean isSend(MQDataAble mqData){
        boolean flag = true;
        if(mqbdCorePropertyConfig.isClientSend() == false && DirectionEnum.REQUEST.getCode().equals(mqData.getDirection())){
            flag =  containsModule(mqData);
        }
        if(mqbdCorePropertyConfig.isSolverSend() == false && DirectionEnum.RESPONSE.getCode().equals(mqData.getDirection())){
            flag = containsModule(mqData);
        }
        logger.info("isSend.flag:{}",flag);
        return flag;
    }

    private boolean containsModule(MQDataAble mqData){
        List<String> moduleList =  mqbdCorePropertyConfig.getModuleList();
        if(moduleList != null && moduleList.contains(mqData.getModule())){
            mqData.setState(MqDataStateConstants.DISCARD_MSG);
            mqData.setMsg("非消息队列发送成功");
            logger.info("msg[serial:{}] discard.",mqData.getSerial());
            return false;
        }
        return true;
    }



}
